﻿/*
 * iec104link.cpp
 *
 *  Created on: 2017年2月4日
 *      Author: work
 */

#include <dm/export.hpp>

#define DM_API_PROTOCOL DM_API_EXPORT

#include <dm/protocol/frame104ldu.hpp>

namespace dm{
namespace protocol{

CFrame104Ldu::CFrame104Ldu( const EType& /*type*/ ):m_apduRef(m_asdu,MaxLenOfAsdu){
	m_ctl.all = 0;
}

CFrame104Ldu::CFrame104Ldu( const CFrame104Ldu& frame ):m_apduRef(m_asdu,MaxLenOfAsdu){
	m_ctl.all = frame.m_ctl.all;
	for( dm::uint8 i=0;i<frame.getApduLen();++i ){
		m_asdu[i] = frame.m_asdu[i];
	}
	m_apduRef.checkData(0);
}

CFrame104Ldu& CFrame104Ldu::operator =( const CFrame104Ldu& frame ){
	m_ctl.all = frame.m_ctl.all;
	for( dm::uint8 i=0;i<frame.getApduLen();++i ){
		m_asdu[i] = frame.m_asdu[i];
	}
	m_apduRef.checkData(0);

	return *this;
}

void CFrame104Ldu::setIFrame(){
	m_ctl.all = 0;
	m_ctl.i.id0 = 0;
	m_ctl.i.id1 = 0;
}

void CFrame104Ldu::setSFrame(){
	m_ctl.all = 0;
	m_ctl.s.id0 = 1;
	m_ctl.s.id1 = 0;

	m_apduRef.checkData(0);
}

void CFrame104Ldu::setUFrame(){
	m_ctl.all = 0;
	m_ctl.u.id0 = 3;
	m_ctl.u.id1 = 0;

	m_apduRef.checkData(0);
}

bool CFrame104Ldu::encode( CTxBuffer& buf )const{
	if( buf.getSpace()<6u+getApduLen() )
		return false;

	buf.push(0x68);
	buf.push(4+getApduLen());
	buf.push(m_ctl.bytes,4);
	if( getApduLen()>0 )
		buf.push(m_asdu,getApduLen());

	return true;
}

/**
 * 解析帧
 */
bool CFrame104Ldu::decode( const CRxBuffer& buf,const pos_t& end,pos_t& start,const CFrame* ){
	while( true ){
		// 查找起始字符
		while( buf.dataAt(start)!=0x68 && start!=end )
			++start;

		dm::uint len = end - start;

		// 最小长度是S帧或者U帧6个字符，紧跟着是APDU长度域
		if( len<6u || buf.dataAt(start+1)+2u>len )
			return false;

		// 长度必须是>=4
		if( buf.dataAt(start+1)<4 ){
			++start;
			continue;
		}

		// 可以解析内容了。
		++start;

		dm::uint8 l = buf.dataAt(start);
		l -= 4;
		++start;

		// 获取控制字符4字节8位位组
		buf.getDataAndMovePos(m_ctl.bytes,4,start);

		if( l>0 ){
			// 获取APDU
			buf.getDataAndMovePos( m_asdu,l,start );
			if( !m_apduRef.checkData(l) ){
				// APDU不认识
				return false;
			}
		}

		return true;
	}
}

}
}

